package com.magicalcoder.lowcode.service.apiopen.service.impl;

import com.magicalcoder.lowcode.anotation.column.MagicalColumn;
import com.magicalcoder.lowcode.core.common.exception.BusinessException;
import com.magicalcoder.lowcode.core.utils.*;
import com.magicalcoder.lowcode.service.apiopen.dto.McPageData;
import com.magicalcoder.lowcode.service.apiopen.dto.McQuery;
import com.magicalcoder.lowcode.service.apiopen.dto.McQueryFunSelectDto;
import com.magicalcoder.lowcode.service.apiopen.service.MagicalApiOpenService;
import com.magicalcoder.lowcode.service.apiopen.service.MagicalCoderJpaService;
import com.magicalcoder.lowcode.service.user.util.MagicalUserUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.persistence.*;
import javax.persistence.metamodel.EntityType;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class MagicalApiOpenServiceImpl implements MagicalApiOpenService {

    @Resource
    private EntityManager entityManager;
    @Resource
    private JdbcTemplate jdbcTemplate;

    @Resource
    private MagicalCoderJpaService magicalCoderJpaService;
    private ReflectUtil reflectUtil = new ReflectUtil();
    private static volatile ConcurrentHashMap<String,Class> concurrentHashMap = new ConcurrentHashMap<>();

    @Override
    public <T> T get(T entity) {
        Class clazz = entity.getClass();
        Object id = pkValue(entity);
        if(id==null){
            return null;
//            throw new BusinessException(-1,"缺少主键值");
        }
        return (T)entityManager.find(clazz,translateId(clazz,id));
    }

    @Transactional()
    @Override
    public <T> void persist(T entity) {
        entityManager.persist(entity);
    }

    @Transactional
    @Override
    public <T> T merge(T entity) {
        T newEntity = entityManager.merge(entity);
        entityManager.flush();
        return newEntity;//如果是新增 obj有主键 而entity没主键
    }

    @Transactional
    @Override
    public <T> void remove(T entity) {
        entityManager.remove(entityManager.merge(entity));
    }

    @Transactional
    @Override
    public <T> void batchSave(List<T> entityList) {
        if(ListUtil.isNotBlank(entityList)){
            for(T entity:entityList){
                if(entity!=null){
                    entityManager.merge(entity);
                }
            }
            entityManager.flush();
        }
    }

    @Override
    public <T> List<T> queryList(Class<T> clazz,McQuery mcQuery) {
        Map<String,Class> fieldMap = allFieldMap(clazz);
        Map<String, Object> param = mcQuery.getParam();
        Map<String, String> condition = mcQuery.getCondition();
        StringBuilder hql = new StringBuilder();
        if(ListUtil.isNotBlank(mcQuery.getFields())||ListUtil.isNotBlank(mcQuery.getFunFields())){
            hql.append("select new map(").append(selectSql(fieldMap,mcQuery.getFields(),mcQuery.getFunFields())).append(")");
        }
        hql.append(" from "+clazz.getName() +" where 1=1 ");

        StringBuilder conditionHql =conditionHql(param,condition);
        hql.append(conditionHql);

        StringBuffer orderGroupBy = orderGroupBy(fieldMap,mcQuery.getOrder(),mcQuery.getGroup());
        hql.append(orderGroupBy);

        Query query;
        if(ListUtil.isNotBlank(mcQuery.getFields())){
            query = entityManager.createQuery(hql.toString());
        }else {
            query = entityManager.createQuery(hql.toString(),clazz);
        }
        setJpaQueryParameter(query,mcQuery,fieldMap,clazz);

        if(mcQuery.getPage()!=null ){
            query.setFirstResult((mcQuery.getPage()-1)*mcQuery.getLimit());
        }
        if(mcQuery.getLimit()!=null){
            query.setMaxResults(mcQuery.getLimit());
        }

        List list = query.getResultList();
        if(ListUtil.isNotBlank(list) && ListUtil.isNotBlank(mcQuery.getFields())){
            //真的jpa 会改变返回的数据 key变成下标了
            List<String> fieldArr = mcQuery.getFields();
            for(Object map :list){
                Map<String,Object> item = (Map<String, Object>) map;
                for(int i=0;i< fieldArr.size();i++){
                    String key = fieldArr.get(i);
                    Object value = item.remove(String.valueOf(i));
                    item.put(key,value);
                }
            }
        }
        return list;
    }
    //交给框架序列化
    private <T> Object transelateValue(Class<T> clazz,Class<T> type,String key,Object value){
        if(value instanceof List){
            return GsonUtil.toList(GsonUtil.toJson(value),type);
        }else if(value.getClass().isArray()){
            return value;
        }
        Map<String,Object> map = new HashMap<>();
        map.put(key,value);
        Object result = GsonUtil.toObj(GsonUtil.toJson(map),clazz);

        return reflectUtil.getBeanObjectValue(result,key);
    }

    private Map<String,Class> allFieldMap(Class clazz){
        Field[] fields = clazz.getDeclaredFields();
        Map<String,Class> map = new HashMap<>();
        for(Field field : fields ){
            map.put(field.getName(),field.getType());
        }
        return map;
    }
    //防止注入 暂时支持哪些比较符
    public String safeCondition(String key){
        if(StringUtil.isNotBlank(key)){
            key = key.replaceAll("&lt;","<").replaceAll("&gt;",">");
        }
        Map<String,String> safeMap = new HashMap<>();
        safeMap.put(">",">");
        safeMap.put(">=",">=");
        safeMap.put("=","=");
        safeMap.put("!=","!=");
        safeMap.put("<>","<>");
        safeMap.put("<","<");
        safeMap.put("<=","<=");
        safeMap.put("in","in");
        safeMap.put("not in","not in");
        safeMap.put(">>",">>");
        safeMap.put("<<","<<");
        safeMap.put("like","like");
        safeMap.put("not like","not like");
        safeMap.put("between","between");
        if(safeMap.containsKey(key.toLowerCase())){
            return safeMap.get(key.toLowerCase());
        }
        return "=";
    }
    private void checkCompare(String param,Object value,String compare){
        if(value instanceof Number){
            if(compare.contains("like")){
                throw new BusinessException(param+"属于数值，暂不支持"+compare+"查询比较符,推荐您配置大于小于等于这种");
            }
        }
    }
    private StringBuilder conditionHql(Map<String, Object> param,Map<String, String> condition){
        StringBuilder conditionHql = new StringBuilder();
        if(param!=null && !param.isEmpty()){
            for(String key:param.keySet()){
                Object value = param.get(key);
                if(isBlankList(value)){
                    continue;//空数组都不支持
                }
                if(value!=null){
                    if(condition!=null && condition.containsKey(key)){
                        String safeCompare = safeCondition(condition.get(key));
                        checkCompare(key,value,safeCompare);
                        if(safeCompare.contains("in")||safeCompare.contains("not in")){
                            if(value instanceof List){
                                if(ListUtil.isNotBlank((List)value)){
                                    conditionHql.append(" and ").append(key).append(" ").append(safeCompare).append(" (:").append(key).append(")");
                                }
                            }
                        }else if("between".equals(safeCompare)){
                            if(value instanceof List){
                                List vList = (List)value;
                                if(ListUtil.isNotBlank(vList)){
                                    if(vList.size()==2){
                                        if(!isBlankAndNull(vList.get(0))){
                                            if(!isBlankAndNull(vList.get(1))){
                                                conditionHql.append(String.format(" and (%s >= :%s and %s <= :%s)",key,key,key,key+"$1"));
                                            }else {
                                                conditionHql.append(String.format(" and %s >= :%s",key,key));
                                            }
                                        }else {
                                            if(!isBlankAndNull(vList.get(1))){
                                                conditionHql.append(String.format(" and %s <= :%s",key,key));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        /*else if(safeCompare.equals("like")||safeCompare.equals("not like")){
                            conditionHql.append(safeCompare).append(" ").append("%:").append(key).append("%");
                        }*/
                        else {
                            conditionHql.append(" and ").append(key).append(" ").append(safeCompare).append(" ").append(":").append(key);
                        }
                    }else {
                        if(value instanceof List){
                            if(ListUtil.isNotBlank((List)value)){
                                conditionHql.append(" and ").append(key).append(" ").append("in").append(" ").append("(:").append(key).append(")");
                            }
                        }else {
                            conditionHql.append(" and ").append(key).append(" ").append("=:").append(key);
                        }
                    }
                }
            }
        }
        return conditionHql;
    }
    private boolean isBlankAndNull(Object v){
        if(v==null){
            return true;
        }
        if(v instanceof String){
            return StringUtil.isBlank((String)v);
        }
        return false;
    }
    private <T> void setJpaQueryParameter(Query query, McQuery mcQuery, Map<String,Class> fieldMap, Class<T> clazz){
        Map<String, Object> param = mcQuery.getParam();
        Map<String, String> condition = mcQuery.getCondition();
        if(param!=null && !param.isEmpty()){
            for(String key:param.keySet()){
                Object value = param.get(key);
                if(isBlankList(value)){
                    continue;//空数组都不支持
                }
                Class type = fieldMap.get(key);
                if(value!=null && type!=null) {
                    if(type.isAssignableFrom(List.class)){//属性就被设置成了数组
                        if(listIsBlank(value)){
                            continue;
                        }
                        List values = (List)value;
                        List<List> newValue = new ArrayList<>();
                        newValue.add(values);

                        if(condition!=null && condition.containsKey(key)){
                            String compare = condition.get(key).toLowerCase();
                            if(compare.contains("like")){
                                List v = new ArrayList(values.size());
                                for(int i=0;i<values.size();i++){
                                    v.add("%"+values.get(i)+"%");
                                }
                                newValue.clear();
                                newValue.add(v);
                                setParameter(query,key,compare,newValue);
                            }else {
                                setParameter(query,key,compare, newValue);//in 语句 使用List对象即可
                            }
                        }else {
                            setParameter(query,key, null,newValue);
                        }
                    }else {
                        if(value instanceof List){//这种情况就是集合属性字段作为入参查询了 但是属性却不是数组
                            List newValue = new ArrayList();
                            if(ListUtil.isNotBlank((List)value)){
                                if(((List) value).get(0) instanceof List){
                                    for(int i=0;i<((List) value).size();i++){
                                        newValue.addAll((List)((List) value).get(i));
                                    }
                                    value = newValue;
                                    if(listIsBlank(value)){
                                        continue;
                                    }
                                }
                            }else {//空数组
                                continue;
                            }

                        }
                        if(condition!=null && condition.containsKey(key)){
                            String compare = condition.get(key).toLowerCase();
                            if(compare.contains("like")){
                                setParameter(query,key,compare,"%"+value+"%");
                            }
                            else if("between".equals(compare)){
                                if(value instanceof List){
                                    List vList = (List)value;
                                    if(ListUtil.isNotBlank(vList)){
                                        if(vList.size()==2){
                                            if(!isBlankAndNull(vList.get(0))){
                                                if(!isBlankAndNull(vList.get(1))){
                                                    setParameter(query,key,compare,transelateValue(clazz,type,key,vList.get(0)));
                                                    setParameter(query,key+"$1",compare,transelateValue(clazz,type,key,vList.get(1)));
                                                }else {
                                                    setParameter(query,key,compare,transelateValue(clazz,type,key,vList.get(0)));
                                                }
                                            }else {
                                                if(!isBlankAndNull(vList.get(1))){
                                                    setParameter(query,key,compare,transelateValue(clazz,type,key,vList.get(1)));
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            else {
                                setParameter(query,key, compare,transelateValue(clazz,type,key,value));//in 语句 使用List对象即可
                            }
                        }else {//普通属性 框架智能纠正值
                            setParameter(query,key, null,transelateValue(clazz,type,key,value));
                        }
                    }

                }
            }
        }
    }
    private void setParameter(Query query,String name,String compare,Object value){
        if(StringUtil.isNotBlank(compare)){
            if(compare.contains("in")){
                if(value instanceof List){
                    if(ListUtil.isBlank((List)value)){
                        return;
                    }
                }else {
                    return;
                }
            }
        }
        query.setParameter(name,value);
    }

    private StringBuffer selectSql(Map<String,Class> fieldMap,List<String> fields,List<McQueryFunSelectDto> funFields){
        StringBuffer sql = new StringBuffer();
        boolean preFields = false;
        if(ListUtil.isNotBlank(fields)){
            sql.append(ListUtil.join(fields,","));
            preFields = true;
        }
        if(ListUtil.isNotBlank(funFields)){
            int i=0;
            for(McQueryFunSelectDto fun:funFields){
                if(i==0){
                    if(preFields){
                        sql.append(",");
                    }
                }else {
                    sql.append(",");
                }
                String funName = fun.getFunc();
                String name = fun.getName();
                if(!fieldMap.containsKey(name)){
                    throw new BusinessException(-1,funName+"函数的字段名不存在"+name);
                }
                String as = fun.getAs();
                sql.append(funName).append("(").append(name).append(") as ").append(as);
                i++;
            }
        }
        return sql;
    }
    private StringBuffer orderGroupBy(Map<String,Class> fieldMap,List<Map<String,String>> orders,List<String> groups){
        StringBuffer sql = new StringBuffer();
        //group by
        if(ListUtil.isNotBlank(groups)){
            sql.append(" group by ");
            for(String group:groups){
                if(!fieldMap.containsKey(group)){
                    continue;
                }
                sql.append(group).append(",");
            }
        }
        if(sql.toString().equals(" group by ")){
            sql.delete(0,sql.length());
        }else {
            if(sql.length()>0){
                sql.deleteCharAt(sql.length()-1);
            }
        }
        //order by
        if(ListUtil.isNotBlank(orders)){
            sql.append(" order by ");
            for(Map<String,String> order : orders){
                Set<String> keys = order.keySet();
                for(String key:keys){
                    if(!fieldMap.containsKey(key)){
                        continue;
                    }
                    String descAsc = order.get(key);
                    if(!descAsc.equalsIgnoreCase("desc")&&!descAsc.equalsIgnoreCase("asc")){
                        throw new BusinessException(-1,"排序类型仅支持desc或asc");
                    }

                    sql.append(key).append(" ").append(descAsc).append(",");
                }
            }
        }
        if(sql.toString().equals(" order by ")){
            sql.delete(0,sql.length());
        }else {
            if(sql.length()>0){
                sql.deleteCharAt(sql.length()-1);
            }
        }
        return sql;
    }
    @Override
    public <T> McPageData<T> queryPageData(Class<T> clazz, McQuery mcQuery) {
        Map<String,Class> fieldMap = allFieldMap(clazz);
        Map<String, Object> param = mcQuery.getParam();
        Map<String, String> condition = mcQuery.getCondition();
        StringBuilder conditionHql =conditionHql(param,condition);

        List list = queryList(clazz,mcQuery);
        //查询个数的
        StringBuilder hqlCount= new StringBuilder("select count(*) from "+clazz.getName()+" where 1=1 ");
        TypedQuery<Long> queryCount = entityManager.createQuery(hqlCount.append(conditionHql).toString(),Long.class);
        setJpaQueryParameter(queryCount,mcQuery,fieldMap,clazz);
        McPageData mcPageData = new McPageData(Integer.valueOf(queryCount.getSingleResult().toString()),list);
        return mcPageData;
    }
    //数组是否为空
    private  boolean listIsBlank(Object value){
        if(value!=null){
            if(value instanceof List){
                return ListUtil.isBlank((List)value);
            }
        }
        return true;
    }
    //是否是空数组
    private  boolean isBlankList(Object value){
        if(value!=null){
            if(value instanceof List){
                return ListUtil.isBlank((List)value);
            }
        }
        return false;
    }
    /**
     *
     * @param catalog
     * @param schema
     * @param tableName
     * @return
     */
    @Override
    public Class scannerClass(String catalog,String schema,String tableName){
        Class clazz = scannerCacheClass(catalog,schema,tableName);
        if(clazz==null){
            String catalogMsg = "";
            if(StringUtil.isNotBlank(catalog)){
                catalogMsg += "catalog="+catalog;
            }
            if(StringUtil.isNotBlank(schema)){
                catalogMsg += "schema="+schema;
            }
            throw new BusinessException(-1,"jpa未检测到"+tableName+"实体类"+catalogMsg+"，请至【我的项目】-【数据仓库】-右键表【"+tableName+"】【生成代码】");
        }
        return clazz;
    }

    private Class scannerCacheClass(String catalog,String schema,String tableName) {
        String key = buildKey(catalog,schema,tableName);
        if(concurrentHashMap.containsKey(key)){
            return concurrentHashMap.get(key);
        }
        //这里有多线程bug 没锁住 暂时放init初始化bean后执行
        synchronized (MagicalApiOpenServiceImpl.class){
            if(!concurrentHashMap.containsKey(key)){
                synchronized (MagicalApiOpenServiceImpl.class){
                    init();
                    return concurrentHashMap.get(key);
                }
            }
        }
        //这里有多线程bug 没锁住
        return null;
    }

    @Override
    public ConcurrentHashMap<String, Class> concurrentHashMap() {
        return concurrentHashMap;
    }

    @Override
    public Object translateId(Class clazz, Object id) {
        Field[] fields = clazz.getDeclaredFields();
        for(Field field:fields){
            Id idAno = field.getAnnotation(Id.class);
            if(idAno!=null){
                String name = field.getType().getSimpleName();
                if(name.equals("String")){
                    return id.toString();
                }
                else if(name.equals("Long")){
                    return Long.valueOf(id.toString());
                }else if(name.equals("Integer")){
                    return Integer.valueOf(id.toString());
                }
            }
        }
        return id;
    }

    @Override
    public <T> Object pkValue(T entity)  {
        if(entity==null){
            return null;
        }
        Class clazz = entity.getClass();
        Field[] fields = clazz.getDeclaredFields();
        try {
            for(Field field:fields){
                Id idAno = field.getAnnotation(Id.class);
                if(idAno!=null){
                    if(field.isAccessible()){
                        return field.get(entity);
                    }
                    field.setAccessible(true);
                    Object v = field.get(entity);
                    field.setAccessible(false);
                    return v;
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public <T> T buildEntity(Class<T> clazz, Object id) {
        if(id==null){
            return null;
        }
        Field[] fields = clazz.getDeclaredFields();
        T instance = null;
        try {
            instance = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        try {
            String idName = null;
            Class type = null;
            for(Field field:fields){
                Id idAno = field.getAnnotation(Id.class);
                if(idAno!=null){
                    idName = field.getName();
                    type = field.getType();
                    break;
                }
            }
            ReflectUtil util = new ReflectUtil();
            util.setBeanValue(instance,type,idName,id);
        }catch (Exception e){
            e.printStackTrace();
        }
        return instance;
    }

    @Transactional
    @Override
    public void executeSql(String sql) {
        if(StringUtil.isBlank(sql)){
            return ;
        }
        Query query = entityManager.createNativeQuery(sql);
        query.executeUpdate();
//        jdbcTemplate.execute(sql);
        /*namedParameterJdbcTemplate.execute(sql, new PreparedStatementCallback<Object>() {
            @Nullable
            @Override
            public Object doInPreparedStatement(PreparedStatement preparedStatement) throws SQLException, DataAccessException {
                return preparedStatement.execute();
            }
        });*/
    }



    @Resource
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    private String buildKey(String catalog,String schema,String tableName){
        if(StringUtil.isBlank(catalog)){
            catalog = "";
        }else {
            catalog +=".";
        }
        catalog = catalog.replaceAll("\\[|\\]","");
        if(StringUtil.isBlank(schema)){
            schema = "";
        }else {
            schema +=".";
        }
        schema = schema.replaceAll("\\[|\\]","");
        return  (catalog+schema+tableName).toLowerCase();
    }
    private void clearNotNeedField(Map<String, Object> param,Map<String, Class> fieldMap){
        if(param==null){
            return;
        }
        List<String> keys = new ArrayList<>();
        for (String key : param.keySet()) {
            if(!fieldMap.containsKey(key)){
                keys.add(key);
            }
        }
        for(String key:keys){
            param.remove(key);
        }
    }
    @Override
    public Map<String,Object> translateReqParam(Map<String, Object> param,Class clazz,HttpServletRequest request){
        Map<String, Class> fieldMap = new HashMap<>();
        //in条件如何处理
        String webUidFieldName = null;
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();//字段名
            Class type = field.getType();//字段类型
            fieldMap.put(name, type);
            MagicalColumn magicalColumn = field.getAnnotation(MagicalColumn.class);
            if(magicalColumn!=null){
                if(magicalColumn.webUserId()){
                    webUidFieldName = name;
                }
            }
        }
        if(request!=null){
            String webUid = MagicalUserUtil.getWebUserId(request);
            if(StringUtil.isNotBlank(webUid) && StringUtil.isNotBlank(webUidFieldName)){//登录了
                if(param == null){
                    param = new HashMap();
                }
                param.put(webUidFieldName,webUid);
            }
        }
        //清理没用的字段
        clearNotNeedField(param,fieldMap);

        Map<String, Object> singleMap = new HashMap<>();//单一类型入场
        Map<String, Object> arrayMap = new HashMap<>();//数组类型入参
        if (param != null && !param.isEmpty()) {
            for (String key : param.keySet()) {
                Object v = param.get(key);
                if (v == null || StringUtil.isBlank(v.toString())) {
                    continue;
                }
                if(v instanceof List){
                    //传了空数组
                    if(ListUtil.isNotBlank((List)v)){
                        if(((List) v).get(0)!=null){
                            arrayMap.put(key, v);
                            fieldMap.put(key,((List) v).get(0).getClass());
                        }
                    }
                }else if(v.getClass().isArray()){
                    arrayMap.put(key, v);
                    fieldMap.put(key,fieldMap.get(key).getComponentType());
                }else {
                    singleMap.put(key, v);
                }
            }
            param = new HashMap<>();
            if(!singleMap.isEmpty()){
                //先转一波单类型的
                try {
                    String json = GsonUtil.toJson(singleMap);
                    Object obj = GsonUtil.toObj(json, clazz);
                    param = CopyUtil.copyToMap(obj, false);
                } catch (IllegalAccessException e) {
                    throw new BusinessException(-1, e.getMessage());
                }
            }
            if (!arrayMap.isEmpty()) {

                //处理多类型的
                for (String name : arrayMap.keySet()) {
                    Object arrayValue = arrayMap.get(name);
                    Class nameType = fieldMap.get(name);//原始类型
                    List list = GsonUtil.toList(GsonUtil.toJson(arrayValue), nameType);
                    if(ListUtil.isNotBlank(list)){
                        param.put(name, list);
                    }
                }
            }
        }
        return param;
    }
    @Override
    public McQuery toMcQuery(HttpServletRequest request,Class clazz,Map<String,Object> req,Integer page,Integer limit) {
        Map<String, Object> param = (Map<String, Object>) req.get("param");
        Map<String, String> condition = (Map<String, String>) req.get("condition");
        Map<String,Class> fieldMap = allFieldMap(clazz);
        //转一波参数 防止类型不匹配
        translateReqParam(param,clazz,request);
        //构造入参
        McQuery mcQuery = new McQuery();
        mcQuery.setPage(page);
        mcQuery.setLimit(limit);
        mcQuery.setCondition(condition);
        mcQuery.setParam(param);
        mcQuery.setFields(validateFields((List<String>) req.get("fields"),fieldMap));
        mcQuery.setGroup(validateFields((List<String>) req.get("group"),fieldMap));
        mcQuery.setFunFields((List)req.get("funFields"));
        mcQuery.setOrder((List)req.get("order"));
        return mcQuery;
    }
    private List<String> validateFields(List<String> fields,Map<String,Class> fieldMap){
        if(ListUtil.isBlank(fields)){
            return null;
        }
        if(ListUtil.isNotBlank(fields)){
            List<String> result = new ArrayList<>();
            for(String field:fields){
                if(StringUtil.isNotBlank(field)){
                    if(!fieldMap.containsKey(field)){
//                        (-1,field+"字段不存在");
                    }else {
                        result.add(field);
                    }
                }
            }
            return result;
        }
        return null;
    }

    @Override
    public String pkName(String catalog, String schema, String tableName) {
        Class clazz = scannerClass(catalog,schema,tableName);
        return pkName(clazz);
    }
    public String pkName(Class clazz){
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field f:declaredFields){
            String name = f.getName();
            Id id = f.getAnnotation(Id.class);
            if(id!=null){
                return name;
            }
        }
        return null;
    }

    @Transactional
    @Override
    public Map<String, Object> removeParentChildren(Map<String, Object> parent) {
        magicalCoderJpaService.removeParentChildren(parent);
        return null;
    }

    @Transactional
    @Override
    public Map<String, Object> saveParentChildren(Map<String, Object> parent) {
        return magicalCoderJpaService.saveParentChildren(parent);
    }

    @PostConstruct
    public void init(){
        EntityManagerFactory entityManagerFactory = entityManager.getEntityManagerFactory();
        Set<EntityType<?>> entitys = entityManagerFactory.getMetamodel().getEntities();
        for(EntityType entity : entitys){
            Class targetClass = entity.getBindableJavaType();
            Table table = (Table) targetClass.getAnnotation(Table.class);
            String anTableName = table.name().replaceAll("\\[|\\]","");
            String anoCatalog = table.catalog();
            String anoSchema = table.schema();
            concurrentHashMap.put(buildKey(anoCatalog,anoSchema,anTableName),targetClass);
            if(anTableName.toLowerCase().equals("magical_coder_admin_user")){
                //兼容下老的代码
                concurrentHashMap.put(buildKey(anoCatalog,anoSchema,"magical_coder_manage_admin_user"),targetClass);
            }
        }
    }

}

/*
                            SingleTableEntityPersister persister = (SingleTableEntityPersister) entity.getValue();
                            Iterable<AttributeDefinition> attributes = persister.getAttributes();
                            String entityName = targetClass.getSimpleName();//Entity的名称
                            String tableNames = persister.getTableName();//Entity对应的表的英文名

                            System.out.println("类名：" + entityName + " => 表名：" + tableName);*/

//属性
                            /*for (AttributeDefinition attr : attributes) {
                                String propertyName = attr.getName(); //在entity中的属性名称
                                String[] columnName = persister.getPropertyColumnNames(propertyName); //对应数据库表中的字段名
                                String type = "";
                                PropertyDescriptor targetPd = BeanUtils.getPropertyDescriptor(targetClass, propertyName);
                                if (targetPd != null) {
                                    type = targetPd.getPropertyType().getSimpleName();
                                }
                                System.out.println("属性名：" + propertyName + " => 类型：" + type + " => 数据库字段名：" + columnName[0]);
                            }*/
/*
                        Map<String,Object> entityMap = SpringUtil.getCtx().getBeansWithAnnotation(Entity.class);
                        Map<String,Object> tableMap = SpringUtil.getCtx().getBeansWithAnnotation(Table.class);
                        for(String beanName:entityMap.keySet()){
                            if(tableMap.containsKey(beanName)){
                                Object bean = tableMap.get(beanName);
                                String cglibClass = bean.getClass().getName();//被spring代理 变成了xxx$$spr
                                if(StringUtil.isNotBlank(cglibClass)){
                                    String[] arr = cglibClass.split("\\$");
                                    String realClazz = arr[0];
                                    Class clazz = Class.forName(realClazz);
                                    Table table = (Table) clazz.getAnnotation(Table.class);
                                    String anoTableName = table.name();
                                    concurrentHashMap.put(anoTableName,clazz);
                                }
                            }
                        }*/
/*                        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
                        scanner.addIncludeFilter(new AnnotationTypeFilter(Table.class));
                        for (BeanDefinition bd : scanner.findCandidateComponents(entityScan)) {
                            String className = bd.getBeanClassName();
                            Class clazz = Class.forName(className);
                            Table table = (Table) clazz.getAnnotation(Table.class);
                            String anoTableName = table.name();
                            concurrentHashMap.put(anoTableName,clazz);
                        }*/
